package com.dhecp.project.storage.service.impl;

import com.alibaba.fastjson.JSON;
import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.common.utils.MessageUtils;
import com.dhecp.common.utils.RandomValueUtils;
import com.dhecp.common.utils.TypeUtils;
import com.dhecp.core.constant.DataFiltering;
import com.dhecp.core.utils.PageUtils;
import com.dhecp.core.utils.ReflectUtils;
import com.dhecp.framework.util.ShiroUtils;
import com.dhecp.project.business.domain.ProductActiveComponent;
import com.dhecp.project.business.mapper.ProductActiveMapper;
import com.dhecp.project.common.domain.*;
import com.dhecp.project.common.mapper.ModuleNidAndBidMapper;
import com.dhecp.project.common.service.impl.BaseModuleServiceImpl;
import com.dhecp.project.purchase.domain.PurchasePlan;
import com.dhecp.project.purchase.domain.PurchasePlanSon;
import com.dhecp.project.purchase.mapper.PurchasePlanMapper;
import com.dhecp.project.purchase.mapper.PurchasePlanSonMapper;
import com.dhecp.project.storage.domain.ProductAssemble;
import com.dhecp.project.storage.domain.PurchasingError;
import com.dhecp.project.storage.domain.Putaway;
import com.dhecp.project.storage.mapper.ProductAssembleMapper;
import com.dhecp.project.storage.mapper.PurchasingErrorMapper;
import com.dhecp.project.storage.mapper.PutawayMapper;
import com.dhecp.project.storage.service.PutawayService;
import com.dhecp.project.system.service.SysDictionaryForFieldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collector;

/**
 * @program: kjecp
 * @description: 质检上架单
 * @author: hlf
 * @create: 2022-09-01 15:11
 */
@Service
public class PutawayserviceImpl extends BaseModuleServiceImpl implements PutawayService {


    @Autowired
    private PutawayMapper storageMapper;

    @Autowired
    private ModuleNidAndBidMapper moduleNidAndBidMapper;
    @Autowired
    private PurchasingErrorMapper purchasingErrorMapper;
    @Autowired
    private PurchasePlanMapper purchasePlanMapper;
    @Autowired
    private PurchasePlanSonMapper purchasePlanSonMapper;
    @Autowired
    private ProductActiveMapper productActiveMapper;
    @Autowired
    private ProductAssembleMapper assembleMapper;

    @Autowired
    private SysDictionaryForFieldService dictionaryForFieldService;

    /**
     * @Description: 查询前一单NID、BID
     * @Param: [params] nid 必要参数：当前 单据编码
     * @return: com.dhecp.common.core.domain.AjaxResult  (data.nid 前一单NID， data.bid 前一单BID)
     * @Author: hlf
     * @date: 2022-05-09 10:08
     */
    @Override
    public AjaxResult queryLastNid(Map<String, Object> params) throws Exception {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        if (params.get("nid") == null || params.get("nid") == "") {
            params.put("nid", "0");
        }
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        ModuleNID moduleNID = storageMapper.selectLastNid(params);
        if (moduleNID == null) {
            dataMap.put("nid", "0");
            dataMap.put("bid", "0");
            return AjaxResult.warn(MessageUtils.message("module.warn.isfirstnid"), TypeUtils.mapToJson(dataMap).toString());
        }
        dataMap.put("nid", moduleNID.getNid().toString());
        dataMap.put("bid", moduleNID.getBid().toString());
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), TypeUtils.mapToJson(dataMap).toString());
    }


    /**
     * @Description: 查询后一单NID、BID
     * @Param: [params] nid 必要参数：当前 单据编码
     * @return: com.dhecp.common.core.domain.AjaxResult  (data.nid 后一单NID， data.bid 后一单BID)
     * @Author: hlf
     * @date: 2022-05-09 10:09
     */
    @Override
    public AjaxResult queryNextNid(Map<String, Object> params) throws Exception {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        if (params.get("nid") == null || params.get("nid") == "" || "0".equals(params.get("nid").toString())) {
            dataMap.put("nid", "0");
            dataMap.put("bid", "0");
            return AjaxResult.warn(MessageUtils.message("module.warn.isfinallynid"), TypeUtils.mapToJson(dataMap).toString());
        }
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        ModuleNID moduleNID = storageMapper.selectNextNid(params);
        if (moduleNID == null) {
            dataMap.put("nid", "0");
            dataMap.put("bid", "0");
            return AjaxResult.warn(MessageUtils.message("module.warn.isfinallynid"), TypeUtils.mapToJson(dataMap).toString());
        }
        dataMap.put("nid", moduleNID.getNid().toString());
        dataMap.put("bid", moduleNID.getBid().toString());
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), TypeUtils.mapToJson(dataMap).toString());
    }


    /**
     * @Description: 查询指定单nid的首记录
     * @Param: [params]
     * @return: com.dhecp.project.storage.domain.Putaway
     * @Author: hlf
     * @date: 2022-05-09 10:10
     */
    @Override
    public Putaway queryFirstRecord(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        return storageMapper.selectFirstRecordByNid(params);
    }

    /**
     * @Description: 查询指定单nid的整单录
     * @Param: [params] nid 必要参数：当前 单据编码
     * @return: java.util.List<com.dhecp.project.storage.domain.Putaway>
     * @Author: hlf
     * @date: 2022-05-09 10:10
     */
    @Override
    public List<Putaway> queryListByNid(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        return storageMapper.selectByNid(params);
    }


    /**
     * @Description: 查询
     * @Param: [params]
     * @return: java.util.List<com.dhecp.project.storage.domain.Putaway>
     * @Author: hlf
     * @date: 2022-05-09 10:10
     */
    @Override
    public List<Putaway> queryList(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));    //常规查询条件SQL语句
        params.put(DataFiltering.DATA_SCODE, dictionaryForFieldService.getDataScode(params));    //数据权限查询条件SQL语句
        PageUtils.startPageStronger();
        return storageMapper.select(params);
    }

    /**
     * @Description: 保存
     * @Param: [params] moduleTable 必要参数：功能唯一标识
     * @Param: [params] infoMap 必要参数：非网格字段（包括头部、底部所有显示和隐藏的字段）
     * @Param: [params] infoItems 必要参数：对应实体类的json格式字符串
     * @return: com.dhecp.common.core.domain.AjaxResult
     * @Author: hlf
     * @date: 2022-05-09 10:10
     */
    @SuppressWarnings("unchecked")
    @Override
    public AjaxResult saveData(Map<String, Object> params) {
        params.put("businessEntity", new Putaway());
        params.put("isAuto", false);
        AjaxResult ajaxResult = this.saveDataBase(params);
        if (!"0".equals(ajaxResult.get("code").toString())) {
            throw new RuntimeException(ajaxResult.get("msg").toString());
        }


        String resNid = "0";
        Map<String, Object> infoMap = (Map<String, Object>) ajaxResult.get("infoMap");
        List<Putaway> businessDataList = (List<Putaway>) ajaxResult.get("businessDataList");


        List<RecordCheck> guidMapList = storageMapper.findRecords(infoMap.get("nid").toString());
        Map<String, Object> guidMap = new HashMap<String, Object>();
        if (!guidMapList.isEmpty()) {
            if (infoMap.get("newNid") != null && "1".equals(infoMap.get("newNid").toString())) { //单号重复验证
                throw new RuntimeException(MessageUtils.message("module.error.retry"));
            }
            for (RecordCheck recordCheck : guidMapList) {
                if (recordCheck != null && recordCheck.getGuid() != null) {
                    guidMap.put(recordCheck.getGuid().toString(), "1");
                }
            }
        }

        if (businessDataList == null || businessDataList.size() == 0) {
            resNid = "0";
        } else {
            resNid = infoMap.get("nid").toString();
            for (Putaway businessData : businessDataList) {
                String guid = "";
                if (businessData.getGuid() == null) {
                    guid = RandomValueUtils.getGUID();
                } else {
                    guid = businessData.getGuid().toString();
                }
                businessData.setGuid(guid);
                for (String field : infoMap.keySet()) { //遍历非网格字段，并赋值到实体中
                    Object fieldValue = infoMap.get(field);
                    ReflectUtils.setValue(businessData, field, fieldValue);
                }

                if (guidMap.get(guid) == null) {/*
                	businessData.setPutawayId("111");
                	businessData.setPutawayName("2222");*/
                    businessData.setCreateTime(new Date());
                    storageMapper.insert(businessData);
                } else {
                    storageMapper.update(businessData);
                    guidMap.remove(guid);
                }

            }
        }

        if (!guidMap.isEmpty()) {
            for (String guid : guidMap.keySet()) {
                storageMapper.delete(guid);
            }
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), resNid);
    }

    /**
     * @Description: 删除
     * @Param: [params]
     * @return: com.dhecp.common.core.domain.AjaxResult
     * @Author: hlf
     * @date: 2022-05-09 10:11
     */
    @Override
    public AjaxResult deleteData(Map<String, Object> params) {
        List<Putaway> businessDataList = JSON.parseArray(params.get("infoItems").toString(), Putaway.class);
        if (businessDataList == null || businessDataList.size() == 0) {
            return AjaxResult.error(MessageUtils.message("module.error.jsontoentyerror"));
        }
        for (Putaway businessData : businessDataList) {

            Map<String, Object> paramsNid = new HashMap<>();
            paramsNid.put("nid", businessData.getNid());
            List<Putaway> putaways = storageMapper.selectByNid(paramsNid);
            for (Putaway item : putaways) {
                storageMapper.delete(item);
            }

        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * @Description: 修改删除标志（预留）
     * @Param: [params] infoItems 必要参数：对应实体类的json格式字符串（仅需 guid 和 deleted）
     * @return: com.dhecp.common.core.domain.AjaxResult
     * @Author: hlf
     * @date: 2022-05-09 10:11
     */
    @Override
    public AjaxResult updateDeleted(Map<String, Object> params) {
        List<UpdateDeleted> updateDeletedList = JSON.parseArray(params.get("infoItems").toString(), UpdateDeleted.class);
        if (updateDeletedList == null || updateDeletedList.size() == 0) {
            return AjaxResult.error(MessageUtils.message("module.error.jsontoentyerror"));
        }
        for (UpdateDeleted updateDeleted : updateDeletedList) {
            storageMapper.updateDeleted(updateDeleted);
        }
        return AjaxResult.success(MessageUtils.message("module.success.issuccess"));
    }

    /**
     * @Description: 流转  —— 添加流程任务、修改流程状态及生效标志
     * @Param: [params] tableDataId 必要参数：单据编码（nid）
     * @return: com.dhecp.common.core.domain.AjaxResult
     * @Author: hlf
     * @date: 2022-05-09 10:11
     */
    @Override
    public AjaxResult updateFlowGo(Map<String, Object> params) {
        Map<String, Object> infoMap = new HashMap<String, Object>();
        String nid = "0";
        if (params.get("tableDataId") == null || params.get("tableDataId") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack", "单据编码【tableDataId】"));
        } else {
            nid = params.get("tableDataId").toString();
        }
        params.put("nid", nid);
        List<Putaway> businessDataList = storageMapper.selectByNid(params);
        if (businessDataList == null || businessDataList.size() == 0) {
            return AjaxResult.error(MessageUtils.message("module.error.nodata"));
        } else {
            infoMap.put("cid", businessDataList.get(0).getCid());
            infoMap.put("bUser", businessDataList.get(0).getbUser());
            infoMap.put("bDept", businessDataList.get(0).getbDept());
            infoMap.put("procInstId", businessDataList.get(0).getProcInstId());
            infoMap.put("activeFlow", businessDataList.get(0).getActiveFlow());
            infoMap.put("createTime", businessDataList.get(0).getCreateTime());
            params.put("infoMap", TypeUtils.mapToJson(infoMap).toString());
            params.put("activeFlowOld", businessDataList.get(0).getActiveFlow());
        }

        //流程处理公共方法，返回单据（流转、回退等）后的流程状态信息
        if (params.get("optType") == null || params.get("optType") == "") {
            params.put("optType", "go");
        }
        UpdateFlow updateFlow = new UpdateFlow();
        updateFlow = this.FlowDealBase(params);

        for (Putaway businessData : businessDataList) {
            updateFlow.setGuid(businessData.getGuid().toString());
            storageMapper.updateFlow(updateFlow);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), nid);
    }

    /**
     * @Description: 退回  —— 添加流程任务、修改流程状态及生效标志
     * @Param: [params] tableDataId 必要参数：单据编码（nid）
     * @return: com.dhecp.common.core.domain.AjaxResult
     * @Author: hlf
     * @date: 2022-05-09 10:11
     */
    @Override
    public AjaxResult updateFlowBack(Map<String, Object> params) {
        Map<String, Object> infoMap = new HashMap<String, Object>();
        String nid = "0";
        if (params.get("tableDataId") == null || params.get("tableDataId") == "") {
            return AjaxResult.error(MessageUtils.message("module.error.lack", "单据编码【tableDataId】"));
        } else {
            nid = params.get("tableDataId").toString();
        }
        params.put("nid", nid);
        List<Putaway> businessDataList = storageMapper.selectByNid(params);
        if (businessDataList == null || businessDataList.size() == 0) {
            return AjaxResult.error(MessageUtils.message("module.error.nodata"));
        } else {
            infoMap.put("cid", businessDataList.get(0).getCid());
            infoMap.put("bUser", businessDataList.get(0).getbUser());
            infoMap.put("bDept", businessDataList.get(0).getbDept());
            infoMap.put("procInstId", businessDataList.get(0).getProcInstId());
            infoMap.put("activeFlow", businessDataList.get(0).getActiveFlow());
            infoMap.put("createTime", businessDataList.get(0).getCreateTime());
            params.put("infoMap", TypeUtils.mapToJson(infoMap).toString());
            params.put("activeFlowOld", businessDataList.get(0).getActiveFlow());
        }

        //流程处理公共方法，返回单据（流转、回退等）后的流程状态信息
        if (params.get("optType") == null || params.get("optType") == "") {
            params.put("optType", "back");
        }
        UpdateFlow updateFlow = new UpdateFlow();
        updateFlow = this.FlowDealBase(params);

        for (Putaway businessData : businessDataList) {

            updateFlow.setGuid(businessData.getGuid().toString());
            storageMapper.updateFlow(updateFlow);
        }

        return AjaxResult.success(MessageUtils.message("module.success.issuccess"), nid);
    }


    /**
     * 修改审核状态
     *
     * @param params
     * @return
     * @author DH-Xxj
     */
    @Override
    public AjaxResult updateType(Map<String, Object> params) {
        List<Putaway> putaways = JSON.parseArray(params.get("infoItems").toString(), Putaway.class);
        for (Putaway item : putaways
        ) {
            List<Putaway> putawayList = storageMapper.findByBID2(item.getBid());


            for (Putaway item2 : putawayList
            ) {
                if (item2.getGoodsAllocation() == null || item2.getGoodsAllocation().equals("")) {
                    item2.setWarehouseAddress(item.getWarehouseAddress());
                    item2.setGoodsAllocation(item.getGoodsAllocation());
                    item2.setGoodsArea(item.getGoodsArea());
                }
                item2.setUpdateTime(new Date());
                item2.setEffectStock(item.getEffectStock());

                item2.setPutawayId(ShiroUtils.getMandatorId());
                item2.setPutawayName(ShiroUtils.getMandatorName());

                //判断是否生效
                if (item.getEffectStock()) {
                    //生成 采购报错单
                    getPurchasingErrorData(putawayList.get(0));

                } else {//退回的时候需要判断是否已生成质检报错单
                    List<PurchasingError> old = purchasingErrorMapper.findByAssID(item.getBid());
                    if (old.size() > 0) {
                        return AjaxResult.warn(item.getBid() + "已生成质检报错单，请先删除！");
                    }
                }

                storageMapper.update(item2);
            }

        }
        return AjaxResult.success("操作成功");

    }


    /**
     * @Description: 根据组装单号查询相关数据
     * @Param: [params]
     * @return: java.util.List<com.dhecp.project.storage.domain.Putaway>
     * @Author: hlf
     * @date: 2022-12-07 17:06
     */
    @Override
    public List<Putaway> selectPutawayList(Map<String, Object> params) throws Exception {
        params.put(DataFiltering.TABLE_ALIAS, "t1");    //查询表别名
        params.put(DataFiltering.DATA_WHERE, dictionaryForFieldService.getWhereStr(params));    //常规查询条件SQL语句
        return storageMapper.selectPutawayList(params);
    }


    /**
     * @Description: 导入
     * @Param: [params]
     * @return: com.dhecp.common.core.domain.AjaxResult
     * @Author: hlf
     * @date: 2022-12-08 9:15
     */
    @Override
    public AjaxResult saveImportData(Map<String, Object> params) {

        List<Putaway> putawayList = JSON.parseArray(params.get("infoItems").toString(), Putaway.class);
        if (putawayList == null || putawayList.size() == 0) {
            return AjaxResult.error("数据包格式有误，请检查！");
        }
        int x = 0;
        for (Putaway item : putawayList) {

            Map<String, Object> params2 = new HashMap<String, Object>();
            params2.put("productID", item.getProductID());
            params2.put("assembleID", item.getAssembleID());
            List<Putaway> putaways = storageMapper.findByBID(params2);

            if (putaways.size() > 0) {
                for (Putaway item2 : putaways
                ) {
                    item2.setEffectStock(true);
                    item2.setUpdateTime(new Date());
                    item2.setNum(item.getNum());
                    item2.setGoodsAllocation(item.getGoodsAllocation());
                    storageMapper.update(item2);
                }
            }
            x++;
        }
        return AjaxResult.success(x + "条数据导入成功");
    }

    public void getPurchasingErrorData(Putaway putaway) {
        //判断是否已生成质检报错单
        List<PurchasingError> old = purchasingErrorMapper.findByAssID(putaway.getBid());
        if (old.size() == 0) {

            try {
                PurchasingError purchasingError = new PurchasingError();
                Map<String, Object> params = new HashMap<>();

                //组装单
                List<ProductAssemble> productAssembles = assembleMapper.listByBid(putaway.getAssembleID());

                //上架单
                List<Putaway> putawayList = storageMapper.findByBID2(putaway.getBid());

                //判断是否满足生成质检报错单的条件
                double spread = 0.00;//价格差额
                if (productAssembles.size() > 0) {

                    for (ProductAssemble productAssemble : productAssembles
                    ) {
                        int planSonNum = 0;//子件采购总数
                        double planSonSum = 0;//子件总额
                        int putAwaySonNum = 0;//上架总数
                        double putAwaySonSum = 0;//上架总额

                        //获取采购子件的数量和总金额
                        planSonNum = productAssemble.getSonNum();
                        planSonSum = planSonNum * productAssemble.getsPrice();

                        //获取实际上架的总额
                        putAwaySonNum = productAssemble.getSonUseTotal() + productAssemble.getSonActualBalance();
                        putAwaySonSum = putAwaySonNum * productAssemble.getsPrice();

                        //计算误差的金额
                        spread = spread + ((planSonSum - putAwaySonSum) > 0 ? (planSonSum - putAwaySonSum) : 0);
                    }

                    //母件上架对应的子件数量+子件单独上架的数量-采购计划的子件数量*子件单价=采购差额 > 5
                    if (spread > 5) {
                        Putaway putAway1 = putawayList.get(0);

                        //生成报错单
                        params.put("moduleTable", "TCC_PURCHASINGERROR");
                        ModuleNidAndBid moduleNidAndBid = moduleNidAndBidMapper.findModuleNidAndBid(params);    //有事务控制，制单异常不跳过单号

//                        int putAwaySonNum = productAssembles.stream()
//                                .filter(item2 -> Objects.equals(item2.getProductID(), item.getSonProductID()))
//                                .mapToInt(item2 -> item.getNum() * (int)Double.parseDouble(item2.getvBz()))
//                                .sum();

                        for (ProductAssemble assemble : productAssembles
                        ) {

                            purchasingError.setNid(moduleNidAndBid.getNid());
                            purchasingError.setBid(moduleNidAndBid.getBid());
                            purchasingError.setGuid(RandomValueUtils.getGUID());
                            purchasingError.setCreateTime(new Date());
                            purchasingError.setbUser(ShiroUtils.getUserId());
                            purchasingError.setvGsBm(assemble.getvGsBm());
                            purchasingError.setvGsMc(assemble.getvGsMc());
                            purchasingError.setvGsJc(assemble.getvGsJc());
                            purchasingError.setpGuid(assemble.getGuid());
                            //表头
                            purchasingError.setPutawayID(putAway1.getBid());//质检上架单
                            purchasingError.setOrderID(assemble.getSonOrderID());//采购订单
                            purchasingError.setProductName(assemble.getProductName());//商品名称
                            purchasingError.setProductID(assemble.getProductID());//商品编号
                            purchasingError.setErrorSum(spread);//误差总金额
                            purchasingError.setState("1");//误差总金额

                            //明细
                            purchasingError.setSonCode(assemble.getSonCode());//子件编码
                            purchasingError.setSonName(assemble.getSonName());//子件名称
                            purchasingError.setSonPurchaseNum(assemble.getSonNum());//子件采购总数
                            purchasingError.setSonStoresNum(assemble.getSonUseTotal() + assemble.getSonActualBalance());//子件上架数量
                            purchasingError.setSonNum(assemble.getSonNum() - purchasingError.getSonStoresNum());//子件误差数量
                            purchasingError.setSonPrice(assemble.getsPrice());//子件单价
                            purchasingError.setClaimsSum(assemble.getsPrice() * purchasingError.getSonNum());//子件需赔偿金额

//                            System.out.println("插入");
//                            if (purchasingError.getSonNum()>0) {
                                purchasingErrorMapper.insert(purchasingError);
//                            }

                        }


                    }

                }


            } catch (Exception e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
            }


        }

    }
}